// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.question.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.SystemConstants;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.*;
import com.liuxinlong.modules.dao.*;
import com.liuxinlong.modules.entity.*;
import com.liuxinlong.modules.question.service.TestQuestionService;
import com.liuxinlong.modules.system.service.FileManageService;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 测试问题服务层实现类
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022年4月2日
 */
@Slf4j
@Service
public class TestQuestionServiceImpl implements TestQuestionService {

    @Autowired
    private TestQuestionDao testQuestionDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private FileManageService fileManageService;

    @Autowired
    private MenuDao menuDao;

    @Autowired
    private DealRecordDao dealRecordDao;

    @Autowired
    private ParameterDao parameterDao;

    @Autowired
    private UserMatterDao userMatterDao;

    @Autowired
    private NotificationDao notificationDao;

    @Override
    public List<Map<String, Object>> pageTestQuestionInfo(Map<String, Object> queryParam) {
        int startNum = (int) queryParam.get("startNum");
        List<TestQuestion> originList = testQuestionDao.pageTestQuestionList(queryParam);
        return completeResult(originList, startNum);
    }

    @Override
    public int getTestQuestionCount(Map<String, Object> queryParam) {
        return testQuestionDao.getTestQuestionCount(queryParam);
    }

    @Override
    @Transactional
    public void addTestQuestionInfo(TestQuestion testQuestion) {
        String id = SnowFlake.nextIdStr();
        testQuestion.setId(id);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        testQuestion.setCreateUser(currentUser.getId());
        testQuestion.setStatus(0);
        testQuestion.setSn(generateQuestionCode());
        String attach = testQuestion.getAttach();
        if (StringUtils.isNotEmpty(attach)) {
            fileManageService.updateBusinessFile(attach, id);
        }
        QuestionDealRecord dealRecord = new QuestionDealRecord();
        dealRecord.setId(SnowFlake.nextIdStr());
        dealRecord.setQuestionId(id);
        dealRecord.setOperateUser(currentUser.getId());
        String content = currentUser.getName() + " 创建问题";
        dealRecord.setContent(content);
        dealRecordDao.insert(dealRecord);
        testQuestionDao.insert(testQuestion);
        parameterDao.updateParameterValue(SystemConstants.GENERATE_QUESTION_PARAM, testQuestion.getSn().substring(7));
        UserMatter userMatter = new UserMatter();
        userMatter.setId(SnowFlake.nextIdStr());
        userMatter.setSourceId(id);
        userMatter.setSourceType(3);
        userMatter.setPendingUser(testQuestion.getOperateUser());
        userMatter.setContent(content + ",待用户处理");
        userMatter.setCreateTime(TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS));
        userMatterDao.insert(userMatter);
//        Notification notification = new Notification();
//        notification.setId(SnowFlake.nextIdStr());
//        notification.setCreateUser(currentUser.getId());
//        notification.setSourceId(id);
//        notification.setContent();
//        notificationDao.insert(notification);
    }

    @Override
    @Transactional
    public void updateTestQuestionInfo(TestQuestion testQuestion) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        if (ObjectUtils.isEmpty(currentUser)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "用户登陆状态异常！");
        }
        String attach = testQuestion.getAttach();
        fileManageService.updateBusinessFile(attach, testQuestion.getId());

        QuestionDealRecord dealRecord = new QuestionDealRecord();
        dealRecord.setId(SnowFlake.nextIdStr());
        dealRecord.setQuestionId(testQuestion.getId());
        dealRecord.setOperateUser(currentUser.getId());
        String content = currentUser.getName() + " 修改问题";
        dealRecord.setContent(content);
        dealRecordDao.insert(dealRecord);
        testQuestionDao.updateById(testQuestion);
    }

    @Override
    @Transactional
    public void deleteTestQuestionInfo(String id) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        if (ObjectUtils.isEmpty(currentUser)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "用户登陆状态异常！");
        }
        TestQuestion testQuestion = testQuestionDao.selectById(id);
        if (!StringUtils.equals(currentUser.getId(), testQuestion.getCreateUser())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "当前用户没有权限修改！");
        }
        QuestionDealRecord dealRecord = new QuestionDealRecord();
        dealRecord.setId(SnowFlake.nextIdStr());
        dealRecord.setQuestionId(testQuestion.getId());
        dealRecord.setOperateUser(currentUser.getId());
        String content = currentUser.getName() + " 废止问题";
        dealRecord.setContent(content);
        dealRecordDao.insert(dealRecord);
        testQuestion.setStatus(5);
        testQuestionDao.updateById(testQuestion);
    }

    @Override
    public void exportTestQuestionInfo(String id, HttpServletResponse response) {
        Map<String, Map<String, String>> menuMap = menuDao.getMenuMap();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        ExcelData data = new ExcelData();
        data.setFileName("测试问题清单导出excel.xlsx");
        List<TestQuestion> questionList = testQuestionDao.getTestQuestionList();
        String[] head = {"序号", "问题单号", "标题", "所属模块", "严重等级", "当前状态", "问题描述", "当前处理人", "提出人", "提出时间"};
        data.setHead(head);
        String[][] dataList = new String[questionList.size()][head.length];
        int index = 0;
        for (TestQuestion item : questionList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = item.getSn();
            dataList[index][2] = item.getTitle();
            dataList[index][3] = StringUtils.isNotEmpty(item.getMenu()) ?
                    menuMap.containsKey(item.getMenu()) ? menuMap.get(item.getMenu()).get("name") : "" : "";
            dataList[index][4] = SeverityLevelEnum.getNameByValue(item.getSeverityLevel());
            dataList[index][5] = QuestionStatusEnum.getNameByValue(item.getStatus());
            dataList[index][6] = item.getRemark();
            dataList[index][7] = StringUtils.isNotEmpty(item.getOperateUser()) ?
                    userMap.containsKey(item.getOperateUser()) ? userMap.get(item.getOperateUser()).get("name") : "" : "";
            dataList[index][8] = StringUtils.isNotEmpty(item.getCreateUser()) ?
                    userMap.containsKey(item.getCreateUser()) ? userMap.get(item.getCreateUser()).get("name") : "" : "";
            dataList[index][9] = item.getCreateTime();
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    @Transactional
    public void dealTestQuestionInfo(String id, String assign, String dealResult, String dealOpinions) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        if (ObjectUtils.isEmpty(currentUser)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "用户登陆状态异常！");
        }
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        TestQuestion testQuestion = testQuestionDao.selectById(id);
        QuestionDealRecord dealRecord = new QuestionDealRecord();
        dealRecord.setId(SnowFlake.nextIdStr());
        dealRecord.setQuestionId(id);
        dealRecord.setOperateUser(currentUser.getId());
        int dealOperate = Integer.parseInt(dealResult);
        String content = currentUser.getName() + " 指派给 " + userMap.get(assign).get("name") + ",处理结果:" +
                DealOperateEnum.getNameByValue(dealOperate) + ",处理意见:" + dealOpinions;
        dealRecord.setContent(content);
        dealRecordDao.insert(dealRecord);
        testQuestion.setOperateUser(assign);
        testQuestion.setStatus(getProcessingStatus(dealOperate));
        testQuestionDao.updateById(testQuestion);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        UserMatter userMatterOld = userMatterDao.getBySourceId(id);
        if (!ObjectUtils.isEmpty(userMatterOld) && userMatterOld.getStatus() == 0) {
            userMatterOld.setDealUser(currentUser.getId());
            userMatterOld.setDealTime(currentTime);
            userMatterOld.setStatus(1);
            userMatterDao.updateById(userMatterOld);
        }
        if (dealOperate == 9) {
            return;
        }
        UserMatter userMatter = new UserMatter();
        userMatter.setId(SnowFlake.nextIdStr());
        userMatter.setSourceId(id);
        userMatter.setSourceType(3);
        userMatter.setPendingUser(testQuestion.getOperateUser());
        userMatter.setContent(content + ",待用户处理");
        userMatter.setCreateTime(currentTime);
        userMatterDao.insert(userMatter);
    }

    @Override
    public List<Map<String, Object>> queryDealRecordList(String id) {
        Map<String, Object> queryParam = new HashMap<>();
        queryParam.put("questionId", id);
        List<QuestionDealRecord> originList = dealRecordDao.listDealRecord(queryParam);
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (ObjectUtil.isEmpty(originList)) {
            return resultList;
        }
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        int sort = 1;
        for (QuestionDealRecord item : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(item);
            map.put("sort", sort);
            map.put("title", userMap.get(item.getOperateUser()).get("name"));
            resultList.add(map);
            sort++;
        }
        return resultList;
    }

    private int getProcessingStatus(int dealOperate) {
        int status;
        switch (dealOperate) {
            case 1:
                status = QuestionStatusEnum.PENDING.getValue();
                break;
            case 2:
                status = QuestionStatusEnum.PENDING.getValue();
                break;
            case 3:
                status = QuestionStatusEnum.RESOLVED.getValue();
                break;
            case 4:
                status = QuestionStatusEnum.RESOLVED.getValue();
                break;
            case 5:
                status = QuestionStatusEnum.RESOLVED.getValue();
                break;
            case 6:
                status = QuestionStatusEnum.RESOLVED.getValue();
                break;
            case 7:
                status = QuestionStatusEnum.PENDING.getValue();
                break;
            case 8:
                status = QuestionStatusEnum.VERIFIED.getValue();
                break;
            case 9:
                status = QuestionStatusEnum.CLOSED.getValue();
                break;
            default:
                status = 0;
        }
        return status;
    }

    /**
     * 补全数据
     *
     * @param originList 原始数据
     * @param startNum   起始数
     * @return 补全数据列表
     */
    private List<Map<String, Object>> completeResult(List<TestQuestion> originList, int startNum) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (ObjectUtil.isEmpty(originList)) {
            return resultList;
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        Map<String, Map<String, String>> menuMap = menuDao.getMenuMap();
        int sort = startNum + 1;
        for (TestQuestion item : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(item);
            map.put("sort", sort);
            if (StringUtils.isNotEmpty(item.getMenu())) {
                map.put("menuName", !ObjectUtils.isEmpty(menuMap.get(item.getMenu())) ? menuMap.get(item.getMenu()).get("name") : "");
            }
            map.put("statusName", QuestionStatusEnum.getNameByValue(item.getStatus()));
            map.put("severityLevelName", SeverityLevelEnum.getNameByValue(item.getSeverityLevel()));
            map.put("createUserName", userMap.get(item.getCreateUser()).get("name"));
            if (StringUtils.isNotEmpty(item.getOperateUser())) {
                map.put("operateUserName", userMap.get(item.getOperateUser()).get("name"));
            }
            if (!ObjectUtils.isEmpty(currentUser)) {
                map.put("modify", StringUtils.equals(currentUser.getId(), item.getCreateUser()));
                map.put("deal", StringUtils.equals(currentUser.getId(), item.getOperateUser())
                        || StringUtils.equals(currentUser.getId(), item.getCreateUser()));
            }
            resultList.add(map);
            sort++;
        }
        return resultList;
    }

    private String generateQuestionCode() {
        SystemParameter sp = parameterDao.getParameterByName(SystemConstants.GENERATE_QUESTION_PARAM);
        if (ObjectUtils.isEmpty(sp)) {
            throw new AosException(ReturnCodes.HTTP_SYSTEM_ERROR);
        }
        int currentSn = Integer.parseInt(sp.getValue());
        currentSn++;
        return "TEST-Q-" + StringUtils.leftPad(String.valueOf(currentSn), 4, '0');
    }
}
